﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Utilities.Configuration;
using Utilities.Xml;

namespace EnglishStudy.Service
{

    public abstract class BaseWebService
    {
        private const string JXML_OUTPUT_TYPE = "xml";

        [SecurityCritical]
        private IRestfulHttpClient restClient;


        public BaseWebService()
            : this(null)
        {
        }

        public BaseWebService(IRestfulHttpClient restClient)
        {
            this.Init(restClient);
        }

        public void Init(IRestfulHttpClient restClient)
        {
            this.restClient = restClient == null ? NewRestfulHttpClient() : restClient;
        }

        public IRestfulHttpClient NewRestfulHttpClient()
        {
            IRestfulHttpClient client =
                (IRestfulHttpClient)ApplicationContext.Instance.GetInstance(typeof(IRestfulHttpClient));
            client.Init(GetBaseUri());

            return client;
        }

        protected abstract Uri GetBaseUri();

        public string DoGet(string serviceQueryStringAndParams, IDictionary<string, string> parms, string acceptMediaType)
        {
            try
            {
                return DoGetAsync(serviceQueryStringAndParams, parms, acceptMediaType).Result;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "";
        }

        protected async Task<string> DoGetAsync(string serviceQueryStringAndParams, IDictionary<string, string> parms, string acceptMediaType)
        {
            try
            {
                IHttpResponseMessage responseMessage = await DoGetBasicAsync(serviceQueryStringAndParams, parms, acceptMediaType);

                return await responseMessage.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return default(string);
            }
        }

        protected virtual Task<IHttpResponseMessage> DoGetBasicAsync(string serviceQueryStringAndParams, IDictionary<string, string> parms, string acceptMediaType)
        {
            parms.Add("output", acceptMediaType);
            return restClient.GetAsync(serviceQueryStringAndParams, parms, null);
        }

        protected async Task<IHttpResponseMessage> DoGetBasicOld(string serviceQueryStringAndParams, IDictionary<string, string> parms, string acceptMediaType)
        {
            parms.Add("output", acceptMediaType);
            return await restClient.GetAsync(serviceQueryStringAndParams, parms, null);
        }

        protected T DoGetXmlDeserialize<T>(string serviceQueryStringAndParams, IDictionary<string, string> parms, string NameSpace)
        {
            try
            {
                string responseText = DoGet(serviceQueryStringAndParams, parms, "xml");

                ////Logger.LogVerbose("responseText=" + responseText);
                T resp = ModelCreator<T>.CreateInstanceFromXml(responseText, NameSpace);
                return resp;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return default(T);
        }

        protected async Task<T> DoGetXmlDeserializeAsync<T>(string serviceQueryStringAndParams, IDictionary<string, string> parms, string nameSpace)
        {
            try
            {
                string responseText = await DoGetAsync(serviceQueryStringAndParams, parms, "xml");

                return await ModelCreator<T>.CreateInstanceFromXmlAsync(responseText, nameSpace);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return default(T);
            }
        }
        protected T DoPostXmlDeserialize<T>(string servicePath, IDictionary<string, string> parms, string nameSpace)
        {
            try
            {
                parms.Add("output", "xml");

                string responseString = DoPostXmlAsync(servicePath, parms).Result;

                T postResponse = ModelCreator<T>.CreateInstanceFromXml(responseString, nameSpace);

                return postResponse;
            }
            catch (Exception e)
            {
                throw new Exception("Exception calling PostGenericRequestAndDeserialize", e);
            }
        }

        protected async Task<T> DoPostXmlDeserializeAsync<T>(string servicePath, IDictionary<string, string> parms, string nameSpace)
        {
            try
            {
                parms.Add("output", "xml");
                string responseString = await DoPostXmlAsync(servicePath, parms);
                T postResponse = ModelCreator<T>.CreateInstanceFromXml(responseString, nameSpace);
                /*

                T postResponse = await Task.Run(() => ModelCreator<T>.CreateInstanceFromXml(responseString, nameSpace));
                */
                return postResponse;
            }
            catch (Exception e)
            {
                throw new Exception("Exception calling PostGenericRequestAndDeserialize", e);
            }
        }

        protected async Task<string> DoPostXmlAsync(string servicePath, IDictionary<string, string> parms)
        {
            try
            {
                IHttpResponseMessage responseMessage = await restClient.PostFormUrlEncodedAsync(servicePath, parms, "application/xml");
                return await responseMessage.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                throw new Exception("Exception calling PostGenericRequestAndDeserialize", e);
            }
        }
        protected async Task<string> DoPostJsonAsync(string servicePath, IDictionary<string, string> parms)
        {
            try
            {
                IHttpResponseMessage responseMessage = await restClient.PostFormUrlEncodedAsync(servicePath, parms, "application/json");
                return await responseMessage.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                throw new Exception("Exception calling PostGenericRequestAndDeserialize", e);
            }
        }

        protected async Task<string> DoPostJsonAsync(string servicePath, IDictionary<string, string> parms, string userName, string etoken)
        {
            try
            {
                //IHttpResponseMessage responseMessage = await restClient.PostFormUrlEncodedAsync(servicePath, parms, "application/json");
                IHttpResponseMessage responseMessage = await restClient.PostFormUrlEncodedAsyncWithUser(userName,etoken,servicePath, parms, "application/json");
                return await responseMessage.ReadAsStringAsync();
            }
            catch (Exception e)
            {
                throw new Exception("Exception calling PostGenericRequestAndDeserialize", e);
            }
        }

        protected async Task<T> DoGetJonAsync<T>(string serviceQueryStringAndParams, IDictionary<string, string> parms)
        {
            try
            {
                string responseText = await DoPostJsonAsync(serviceQueryStringAndParams, parms);
                var ms = new MemoryStream(Encoding.Unicode.GetBytes(responseText));
                var ser = new DataContractJsonSerializer(typeof(T));
                return await Task.Run(() => (T)ser.ReadObject(ms));
            }
            catch (Exception ex)
            {
                throw new Exception("Exception calling GetGenericRequestAndDeserialize", ex);
            }
        }

        protected async Task<T> DoGetJonAsync<T>(string serviceQueryStringAndParams, IDictionary<string, string> parms,string userName, string etoken)
        {
            try
            {
                //string responseText = await DoPostJsonAsync(serviceQueryStringAndParams, parms);
                string responseText = await DoPostJsonAsync(serviceQueryStringAndParams, parms,userName,etoken);
                var ms = new MemoryStream(Encoding.Unicode.GetBytes(responseText));
                var ser = new DataContractJsonSerializer(typeof(T));
                return await Task.Run(() => (T)ser.ReadObject(ms));
            }
            catch (Exception ex)
            {
                throw new Exception("Exception calling GetGenericRequestAndDeserialize", ex);
            }
        }

        protected async Task<T> DoPostJonAsync<T>(string serviceQueryStringAndParams, IDictionary<string, string> parms)
        {
            try
            {
                string responseText = await DoPostJsonAsync(serviceQueryStringAndParams, parms);
                var ms = new MemoryStream(Encoding.Unicode.GetBytes(responseText));
                var ser = new DataContractJsonSerializer(typeof(T));
                return await Task.Run(() => (T)ser.ReadObject(ms));
            }
            catch (Exception ex)
            {
                throw new Exception("Exception calling GetGenericRequestAndDeserialize", ex);
            }
        }
    }
}
